package com.lianqi.emcpframework.ddd.gencode.plugin;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Set;

import javax.annotation.processing.Filer;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;

import com.lianqi.emcpframework.ddd.gencode.define.JavaSource;
import com.lianqi.emcpframework.ddd.gencode.define.JavaSourceCollector;
import com.lianqi.emcpframework.ddd.gencode.define.TypeCollector;
import com.squareup.javapoet.JavaFile;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;

/**
 * @program
 * @ClassName AbstractProcessorPlugin
 * @description: 抽象代码生成插件类
 * @author: sky
 * @create: 2019-06-13 15:29
 */
@Getter
@Setter(AccessLevel.PRIVATE)
public abstract class AbstractProcessorPlugin implements ProcessorPlugin {
    /**
     * 类包装控制器
     */
    private final JavaSourceCollector javaSourceCollector = new JavaSourceCollector();
    /**
     * 类型控制器
     */
    private TypeCollector typeCollector;

    protected abstract void process(TypeElement typeElement, Annotation t);

    @Override
    public void init(TypeCollector typeCollector) {
        this.typeCollector = typeCollector;
    }

    @Override
    public void process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (Element element : roundEnv.getRootElements()) {
            if (!(element instanceof TypeElement)) {
                continue;
            }

            for (Class<Annotation> ann : ignoreAnnCls()) {
                if (element.getAnnotation(ann) != null) {
                    break;
                }
            }

            for (Class<Annotation> ann : applyAnnCls()) {
                Annotation annotation = element.getAnnotation(ann);
                if (annotation != null) {
                    process((TypeElement)element, annotation);
                    break;
                }
            }
        }
    }

    /**
     * 代码生成
     * 
     * @param filer
     */
    @Override
    public final void write(Filer filer) {
        javaSourceCollector.getAllJavaSource().forEach(javaSource -> createJavaFile(filer, javaSource));
    }

    private File defaultDirectory() {
        return new File("src/main/java");
    }

    /**
     * 生成java文件
     * 
     * @param filer
     * @param javaSource
     */
    private void createJavaFile(Filer filer, JavaSource javaSource) {
        try {
            JavaFile javaFile = JavaFile.builder(javaSource.getPkgName(), javaSource.getTypeSpec())
                .addFileComment(" This codes are generated automatically. Do not modify!\n").build();
            // javaFile.writeTo(filer);
            javaFile.writeTo(defaultDirectory());
            // System.out.println(javaFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
